﻿using ICPFrameLib.Business;
using ICPFrameLib.Attributes;
using XHRPMIS.Common;
using EFFC.Frame.Net.Base.Common;
using EFFC.Frame.Net.Base.Data.Base;
using EFFC.Frame.Net.Module.Extend.EWRA.Attributes;
using EFFC.Frame.Net.Module.Extend.EWRA.Attributes.Validation;
using EFFC.Frame.Net.Unit.DB.Parameters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EFFC.Extends.LinqDLR2SQL;
using EFFC.Frame.Net.Unit.DB;
using EFFC.Frame.Net.Base.Data;
using System.IO;
using EFFC.Frame.Net.Base.Constants;
using System.Text.RegularExpressions;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using System.Text;
using ICPFrameLib.Common;
using EFFC.Frame.Net.Unit.DB.Datas;

namespace XHRPMIS.Business.v1._0
{
    public partial class MetaDynamicForm : MyRestLogic
{
    RefExpress ref_express = new RefExpress();
    static object lockobj = new object();

    #region CommFunction
    #region 参数加解密校验
    /// <summary>
    /// 通过JsCryptography方式进行解密
    /// </summary>
    /// <param name="input"></param>
    /// <param name="nonce_str"></param>
    /// <returns></returns>
    private string DecryptFromPostDataByJsCryptography(string column)
    {
        var input = ComFunc.nvl(PostData[column]);
        var nonce_str = ComFunc.nvl(PostData["nonce_str"]);
        return DecryptByJsCryptography(input, nonce_str);
    }
    /// <summary>
    /// 判断参数是否为有效加密数据
    /// </summary>
    /// <param name="column"></param>
    /// <returns></returns>
    private bool IsValidFromPostDataByJsCryptography(string column)
    {
        var input = ComFunc.nvl(PostData[column]);
        var nonce_str = ComFunc.nvl(PostData["nonce_str"]);
        return IsValidByJsCryptography(input, nonce_str);
    }
    /// <summary>
    /// 通过JsCryptography方式进行解密
    /// </summary>
    /// <param name="column"></param>
    /// <returns></returns>
    private string DecryptFromQueryStringDataByJsCryptography(string column)
    {
        var input = ComFunc.nvl(QueryString[column]);
        var nonce_str = ComFunc.nvl(QueryString["nonce_str"]);
        return DecryptByJsCryptography(input, nonce_str);
    }
    /// <summary>
    /// 判断参数是否为有效加密数据
    /// </summary>
    /// <param name="column"></param>
    /// <returns></returns>
    private bool IsValidFromQueryStringDataByJsCryptography(string column)
    {
        var input = ComFunc.nvl(QueryString[column]);
        var nonce_str = ComFunc.nvl(QueryString["nonce_str"]);
        return IsValidByJsCryptography(input, nonce_str);
    }
    private string DecryptByJsCryptography(string input, string nonce_str)
    {
        if (string.IsNullOrEmpty(input)) return "";
        var js_key = ComFunc.nvl(TokenPayLoad["js_share_key"]);
        return JsCryptography.ASE_Decrypt(input, js_key).Replace($"#$2#{nonce_str}", "");
    }
    /// <summary>
    /// 判断是否为有效加密数据
    /// </summary>
    /// <param name="input"></param>
    /// <param name="nonce_str"></param>
    /// <returns></returns>
    private bool IsValidByJsCryptography(string input, string nonce_str)
    {
        try
        {
            var a = DecryptByJsCryptography(input, nonce_str);
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    /// <summary>
    /// 将Path中的参数进行转码
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    private string ConvertPathParameter(string str)
    {
        return str.Replace("$slash$", "/");
    }
    #endregion
    /// <summary>
    /// 根据自动填充Method的名称设定，生成对应的值
    /// </summary>
    /// <param name="fix_mathod_name">自动填充Method名称</param>
    /// <param name="length">生成值的长度，Random和Random_Code有效</param>
    /// <returns></returns>
    object genAutoFixValue(string fix_mathod_name, int length = 0)
    {
        switch (fix_mathod_name)
        {
            case "GUID":
                return Guid.NewGuid().ToString();
            case "Random":
                return ComFunc.RandomCode(length);
            case "Random_Code":
                return ComFunc.RandomString(length, true, true, true, false);
            case "Now":
                return DateTime.Now.ToString("yyyy-MM-dd");
            default:
                return fix_mathod_name;
        }
    }
    /// <summary>
    /// 生成自动代码
    /// </summary>
    /// <param name="metaup">元数据up</param>
    /// <param name="metauid">元数据表uid或名称</param>
    /// <param name="column">栏位名称</param>
    /// <param name="format">格式化</param>
    /// <param name="uac_uid">返回的EXTEND_AUTOCODE_UNUSED的UID，用于释放code或用掉code</param>
    /// <returns></returns>
    public object genAutoCode(UnitParameter metaup, string metauid, string column, string format, FrameDLRObject data = null)
    {
        lock (lockobj)
        {
            dynamic metainfo = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "b")
                                where (t.MetaUID == metauid || t.MetaName == metauid)
                                select t).GetQueryList(metaup).FirstOrDefault();
            //识别format中的动态栏位部分
            var reg = new Regex(@"@[A-Za-z0-9_]+@");
            var matches = reg.Matches(format);
            var newformat = format;
            if (data != null)
            {
                foreach (Match m in matches)
                {
                    var key = m.Value.Replace("@", "");
                    var v = data.GetValue(key);
                    var str = "";
                    if (v is DateTime)
                    {
                        str = DateTimeStd.IsDateTimeThen(v, "yyyyMMddHHmmss");
                    }
                    else
                    {
                        str = ComFunc.nvl(v);
                    }
                    newformat = newformat.Replace(m.Value, str);
                }
            }
            //format中含有动态栏位时必须将FormatStr作为查询条件
            dynamic autocodeinfo = (from t in DB.LamdaTable(metaup, "EXTEND_AUTOCODE", "a")
                                    where t.MetaUID == metainfo.MetaUID && t.MetaColumnName == column && t.FormatStr == newformat
                                    select t).GetQueryList(metaup).FirstOrDefault();
            var now = DateTime.Now;
            if (autocodeinfo == null)
            {
                autocodeinfo = FrameDLRObject.CreateInstance();
                autocodeinfo.AC_UID = Guid.NewGuid().ToString();
                autocodeinfo.MetaUID = metainfo.MetaUID;
                autocodeinfo.MetaColumnName = column;
                autocodeinfo.SeqNum = 1;
                autocodeinfo.FormatStr = newformat;
                autocodeinfo.CurrentCode = string.Format(newformat, autocodeinfo.SeqNum)
                    .Replace("yyyy", now.ToString("yyyy"))
                    .Replace("yy", now.ToString("yy"))
                    .Replace("MM", now.ToString("MM"))
                    .Replace("dd", now.ToString("dd"))
                    .Replace("HH", now.ToString("HH"))
                    .Replace("mm", now.ToString("mm"))
                    .Replace("ss", now.ToString("ss"))
                    .Replace("fff", now.ToString("fff"));

                DB.QuickInsert(metaup, "EXTEND_AUTOCODE", autocodeinfo);
            }
            else
            {
                var tmp = string.Format(newformat, autocodeinfo.SeqNum)
                    .Replace("yyyy", now.ToString("yyyy"))
                    .Replace("yy", now.ToString("yy"))
                    .Replace("MM", now.ToString("MM"))
                    .Replace("dd", now.ToString("dd"))
                    .Replace("HH", now.ToString("HH"))
                    .Replace("mm", now.ToString("mm"))
                    .Replace("ss", now.ToString("ss"))
                    .Replace("fff", now.ToString("fff"));
                string maxvalue = ComFunc.nvl(autocodeinfo.CurrentCode);
                //如果tmp与CurrentCode相同，则说明seqnum需要继续累加，不同则表明seqnum需要从1开始
                if (tmp == maxvalue)
                {
                    autocodeinfo.SeqNum = IntStd.IsNotIntThen(autocodeinfo.SeqNum) + 1;
                    autocodeinfo.CurrentCode = string.Format(newformat, autocodeinfo.SeqNum)
                          .Replace("yyyy", now.ToString("yyyy"))
                          .Replace("yy", now.ToString("yy"))
                          .Replace("MM", now.ToString("MM"))
                          .Replace("dd", now.ToString("dd"))
                          .Replace("HH", now.ToString("HH"))
                          .Replace("mm", now.ToString("mm"))
                          .Replace("ss", now.ToString("ss"))
                          .Replace("fff", now.ToString("fff"));
                }
                else
                {
                    autocodeinfo.SeqNum = 1;
                    autocodeinfo.CurrentCode = string.Format(newformat, autocodeinfo.SeqNum)
                         .Replace("yyyy", now.ToString("yyyy"))
                         .Replace("yy", now.ToString("yy"))
                         .Replace("MM", now.ToString("MM"))
                         .Replace("dd", now.ToString("dd"))
                         .Replace("HH", now.ToString("HH"))
                         .Replace("mm", now.ToString("mm"))
                         .Replace("ss", now.ToString("ss"))
                         .Replace("fff", now.ToString("fff"));
                }

                DB.QuickUpdate(metaup, "EXTEND_AUTOCODE", new
                {
                    autocodeinfo.SeqNum,
                    autocodeinfo.CurrentCode
                }, new
                {
                    autocodeinfo.AC_UID
                });
            }
            return autocodeinfo.CurrentCode;
        }
    }

    /// <summary>
    /// 针对主从表构建树结构表
    /// </summary>
    /// <param name="metaup"></param>
    /// <param name="tablename">目标table的名称</param>
    /// <returns>[{
    /// MetaUID:'元数据表UID',
    /// MetaName:'元数据表名',
    /// MetaMainUID:'关联主表UID',
    /// MetaMainShowColumn:'关联主表的显示栏位',
    /// level:'层级'
    /// }]</returns>
    private List<MetaDataUtilities.MetaTable> BuildCadecaseMS_MetaTreeInfo(UnitParameter metaup, string tablename)
    {
        var tablelist = MetaDataUtilities.GetAllTables(metaup);
        //建立树状结构
        var tree_tables = new List<FrameDLRObject>();
        Action<string, int> tree_build = null;
        tree_build = delegate (string p, int level)
        {
            var l = tablelist.Where(w => ComFunc.nvl(w.MetaMainUID) == p).ToList();
            if (l.Count <= 0) return;
            foreach (var item in l)
            {
                item.TreeLevel = level + 1;
                //递归调用
                string pk = ComFunc.nvl(item.MetaUID);
                tree_build(pk, item.TreeLevel);
            }
        };
        tree_build.Invoke("", 0);
        //根据层级找出当前要抓取的表
        var lasttableinfo = tablelist.Where(w => ComFunc.nvl(w.MetaName) == tablename).FirstOrDefault();
        if (lasttableinfo == null) return new List<MetaDataUtilities.MetaTable>();

        var needed_tree_tables = new List<MetaDataUtilities.MetaTable>();
        needed_tree_tables.Add(lasttableinfo);
        Action<string> needed_table_build = null;
        needed_table_build = delegate (string p_uid)
        {
            var l = tablelist.Where(w => ComFunc.nvl(w.MetaUID) == p_uid).FirstOrDefault();
            if (l == null) return;
            needed_tree_tables.Add(l);
            needed_table_build.Invoke(ComFunc.nvl(l.MetaMainUID));
        };
        needed_table_build(ComFunc.nvl(lasttableinfo.MetaMainUID));

        return needed_tree_tables;
    }
    /// <summary>
    /// 引用表达式用用于根据table和栏位获取树结构表中本节点值及其所有子节点值
    /// </summary>
    /// <param name="up"></param>
    /// <param name="metaup"></param>
    /// <param name="cur_table"></param>
    /// <param name="column"></param>
    /// <param name="is_parent_column"></param>
    /// <returns></returns>
    object[] RefExpreeTreeIn(UnitParameter up, UnitParameter metaup, string cur_table, string column, object column_value, bool is_parent_column)
    {
        var table = cur_table;
        var table_uid = "";
        var column_refexprss = "";
        dynamic metainfo = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
                            where t.MetaUID == cur_table || t.MetaName == cur_table
                            select t).GetQueryList(metaup).FirstOrDefault();
        if (metainfo == null) return new object[] { };
        table_uid = metainfo.MetaUID;
        if (is_parent_column)
        {
            dynamic parentinfo = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
                                  where t.MetaUID == metainfo.MetaMainUID
                                  select t).GetQueryList(metaup).FirstOrDefault();
            if (parentinfo == null) return new object[] { };
            table = ComFunc.nvl(parentinfo.MetaName);
            table_uid = parentinfo.MetaUID;
        }

        var columninfo = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA_COLUMNS", "a")
                          where t.MetaUID == table_uid && t.MetaColumnName == column
                          select t).GetQueryList(metaup).FirstOrDefault();
        if (columninfo == null) return new object[] { };
        if (!new string[] { "cadecase_tree", "multi_cadecase_tree" }.Contains(ComFunc.nvl(columninfo.GetValue("MetaDataType")))) return new object[] { ComFunc.nvl(column_value) };
        column_refexprss = ComFunc.nvl(columninfo.GetValue("MetaReference"));
        if (column_refexprss == "") return new object[] { };
        var refexp = new RefExpress().ParseExpress(column_refexprss);
        var rtn = new List<object>();
        rtn.Add(column_value);
        var curinfo = (from t in DB.LamdaTable(up, refexp.TableName, "a")
                       where t.column(refexp.KeyColumn) == column_value
                       select new
                       {
                           t._default_pk,
                           v = t.column(refexp.KeyColumn)
                       }).GetQueryList(up).FirstOrDefault();
        if (curinfo == null) return new object[] { };
        var pk = ComFunc.nvl(curinfo.GetValue("_default_pk"));
        Action<string> tree_build = null;
        tree_build = (pk) =>
        {
            var sublist = (from t in DB.LamdaTable(up, refexp.TableName, "a")
                           where t._default_parent_pk == pk
                           select new
                           {
                               t._default_pk,
                               v = t.column(refexp.KeyColumn)
                           }).GetQueryList(up);
            var tarray = sublist.ToList<object>().Select(d => {
                object rtn = (d as FrameDLRObject).GetValue("v");
                return rtn;
            }).ToArray();
            rtn.AddRange(tarray);
            foreach (var item in sublist)
            {
                tree_build(ComFunc.nvl(item.GetValue("_default_pk")));
            }
        };
        tree_build(pk);

        return rtn.ToArray();
    }
    #region 数据类型处理
    /// <summary>
    /// 将数据转为DB数据格式
    /// </summary>
    /// <param name="ori_value"></param>
    /// <param name="datatype"></param>
    /// <returns></returns>
    object convert2DBValue(object ori_value, string datatype)
    {
        if (ComFunc.nvl(ori_value) == "")
        {
            return DBNull.Value;
        }
        switch (datatype)
        {
            case "time":
                return DateTimeStd.IsDateTimeThen($"1900-01-01 {ori_value}", "yyyy-MM-dd HH:mm:ss");
            case "date":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-MM-dd HH:mm:ss");
            case "datetime":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-MM-dd HH:mm:ss");
            case "date_year":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-01-01 00:00:00", "yyyy", "yyyy-MM-dd");
            case "date_year_month":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-MM-01 00:00:00", "yyyy-M", "yyyy-MM", "yyyy-MM-dd");
            case "multi-file":
                return ComFunc.ToJson(ori_value);
            case "file-base64":
                return ComFunc.ToJson(ori_value, false);
            case "multi-select":
                return ComFunc.ToJson(ori_value);
            case "multi-pop":
                return ComFunc.ToJson(ori_value);
            case "bit":
                return BoolStd.ConvertTo(ori_value, 1, 0);
            case "pictures":
                return ComFunc.ToJson(ori_value);
            case "checkbox":
                return ComFunc.ToJson(ori_value);
            case "multi_cadecase_main":
                return ComFunc.ToJson(ori_value);
            case "multi_cadecase_tree":
                return ComFunc.ToJson(ori_value);
            default:
                return ori_value;
        }
    }
    /// <summary>
    /// 转换成控件的值
    /// </summary>
    /// <param name="ori_value"></param>
    /// <param name="datatype"></param>
    /// <returns></returns>
    object convert2UIValue(object ori_value, string datatype)
    {
        switch (datatype)
        {
            case "time":
                return DateTimeStd.IsDateTimeThen(ori_value, "HH:mm:ss");
            case "date":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-MM-dd");
            case "datetime":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-MM-dd HH:mm:ss");
            case "date_year":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-01-01");
            case "date_year_month":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-MM");
            case "multi-file":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "file-base64":
                return FrameDLRObject.IsJsonThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "multi-select":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "multi-pop":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "bit":
                return BoolStd.IsNotBoolThen(ori_value);
            case "pictures":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "checkbox":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "multi_cadecase_main":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "multi_cadecase_tree":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            default:
                return ori_value;
        }
    }
    #endregion
    /// <summary>
    /// 解析表达式
    /// </summary>
    /// <param name="json"></param>
    /// <returns></returns>
    FrameDLRObject parseFixedExpress(string json)
    {
        var where_context = new Dictionary<string, object>();
        where_context.Add("__now", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
        where_context.Add("__login_id", TokenPayLoad.ID);
        where_context.Add("__login_name", TokenPayLoad["name"]);
        where_context.Add("__user_no", TokenPayLoad["userno"]);
        where_context.Add("__user_name", TokenPayLoad["username"]);
        where_context.Add("__user_type", TokenPayLoad["usertype"]);
        where_context.Add("__role_no", TokenPayLoad["roleno"]);
        where_context.Add("__role_name", TokenPayLoad["rolename"]);
        where_context.Add("__no", TokenPayLoad["no"]);

        try
        {
            FrameDLRObject rtn = FrameDLRObject.CreateInstance(json, FrameDLRFlags.SensitiveCase, where_context.ToArray());
            return rtn;
        }
        catch (Exception ex)
        {
            return null;
        }
    }
    void RemoveFilterEmptry(FrameDLRObject obj)
    {
        foreach (var k in obj.Keys)
        {
            var v = obj.GetValue(k);
            if (v is FrameDLRObject)
            {
                RemoveFilterEmptry((FrameDLRObject)v);
            }
            else
            {
                if (ComFunc.nvl(v) == ""
                    || ComFunc.nvl(v).ToLower() == "null")
                {
                    obj.Remove(k);
                }
            }
        }
    }
    /// <summary>
    /// 设定引用栏位的text
    /// </summary>
    /// <param name="metaup">元数据连接参数</param>
    /// <param name="up">业务数据连接参数</param>
    /// <param name="metainfo">待处理数据表信息</param>
    /// <param name="columns">待处理的栏位信息</param>
    /// <param name="data">数据</param>
    /// <param name="is_filter_deleted">是否过滤删除资料</param>
    void SetRefColumnsText(UnitParameter metaup, UnitParameter up, FrameDLRObject metainfo, List<FrameDLRObject> columns, List<FrameDLRObject> data, bool is_filter_deleted = true)
    {
        SetRefColumnsText(metaup, up, metainfo.ToModel<MetaDataUtilities.MetaTable>(), columns.Select(d => d.ToModel<MetaDataUtilities.MetaColumn>()).ToList(), data, is_filter_deleted);
    }
    /// <summary>
    /// 设定引用栏位的text
    /// </summary>
    /// <param name="metaup">元数据连接参数</param>
    /// <param name="up">业务数据连接参数</param>
    /// <param name="metainfo">待处理数据表信息</param>
    /// <param name="columns">待处理的栏位信息</param>
    /// <param name="data">数据</param>
    /// <param name="is_filter_deleted">是否过滤删除资料</param>
    void SetRefColumnsText(UnitParameter metaup, UnitParameter up, MetaDataUtilities.MetaTable metainfo, List<MetaDataUtilities.MetaColumn> columns, List<FrameDLRObject> data, bool is_filter_deleted = true)
    {
        var reftablelist = MetaDataUtilities.GetAllTables(metaup);
        //获取主表资料
        var main_dic_show = new Dictionary<string, object>();
        var main_dic = new Dictionary<string, FrameDLRObject>();
        if (!string.IsNullOrEmpty(metainfo.MetaMainUID))
        {
            var main_metainfo = (from t in reftablelist
                                 where t.MetaUID == metainfo.MetaMainUID
                                 select t).FirstOrDefault();
            var refs = data.Select(d => ComFunc.nvl(d.GetValue("_default_ref"))).ToArray();
            var main_list = (from t in DB.LamdaTable(up, ComFunc.nvl(main_metainfo.MetaName), "a")
                             where t._default_pk.within(string.Join(",", refs))
                             select t).GetQueryList(up);
            main_dic = main_list.ToDictionary(k => ComFunc.nvl(k.GetValue("_default_pk")), v => v);

            if (main_metainfo != null && !string.IsNullOrEmpty(metainfo.MetaMainShowColumn))
            {
                main_dic_show = main_list.ToDictionary(k => ComFunc.nvl(k.GetValue("_default_pk")), v => v.GetValue(metainfo.MetaMainShowColumn));
            }
        }
        var datatype_dic = columns.ToDictionary(k => k.MetaColumnName, v => v.MetaDataType);
        data = data.Select((p) =>
        {
            FrameDLRObject dobj = p;
            dobj.SetValue("_default_ref__text", "");
            var ref_pk = ComFunc.nvl(dobj.GetValue("_default_ref"));
            if (main_dic_show.ContainsKey(ref_pk))
            {
                dobj.SetValue("_default_ref__text", main_dic_show[ref_pk]);
            }
            foreach (var key in dobj.Keys)
            {
                var v = dobj.GetValue(key);
                dobj.SetValue(key, convert2UIValue(v, datatype_dic.ContainsKey(key) ? datatype_dic[key] : ""));
            }

            return p;
        }).ToList();
        foreach (var c in columns)
        {
            //设定关联栏位的显示text值
            if (c.MetaReference != "" && c.MetaReference != "{}")
            {
                var refResult = ref_express.ParseExpress(c.MetaReference);
                if (refResult == null)
                {
                    continue;
                }
                var reftableinfo = reftablelist.Where(w => w.MetaName == refResult.TableName).FirstOrDefault();
                if (reftableinfo == null) continue;

                var column_value_key = ComFunc.nvl(refResult.KeyColumn);
                var column_text_key = ComFunc.nvl(refResult.TextColumn);

                var column_show_key = from t in refResult.ShowColumns
                                      select new
                                      {
                                          column_name = t
                                      };
                var column_p_pk_key = "_default_parent_pk";
                var column_pk_key = "_default_pk";
                if (reftableinfo.IsDic)
                {
                    column_pk_key = "code";
                    column_p_pk_key = "p_code";
                }
                else
                {
                    column_pk_key = "_default_pk";
                    column_p_pk_key = "_default_parent_pk";
                }
                if (column_value_key == "")
                {
                    if (reftableinfo.IsDic)
                    {
                        column_value_key = "code";
                    }
                    else
                    {
                        column_value_key = "_default_pk";
                    }
                }
                if (column_text_key == "" && column_show_key.Count() > 0)
                {
                    column_text_key = column_show_key.First().column_name;
                }

                if (new string[] { "select", "pop", "radio_button" }.Contains(c.MetaDataType))
                {
                    var ref_dic = new Dictionary<dynamic, dynamic>();
                    if (refResult.Filter.Count <= 0)
                    {
                        var dbexpress = refResult.ToDBExpress(null, is_filter_deleted);
                        dbexpress.SetValue(column_value_key, true);
                        ref_dic = DB.Excute(up, dbexpress, true).QueryData<FrameDLRObject>()
                       .ToDictionary(k => k.GetValue(column_value_key), val => val.GetValue(column_text_key));
                    }

                    foreach (var item in data)
                    {
                        var ref_pk = ComFunc.nvl(item.GetValue("_default_ref"));
                        var main_ref_data = main_dic.ContainsKey(ref_pk) ? main_dic[ref_pk] : null;

                        var v = item.GetValue(c.MetaColumnName);
                        if (v != null)
                        {
                            if (refResult.Filter.Count > 0)
                            {
                                var dbexpress = refResult.ToDBExpress(item, is_filter_deleted, main_ref_data, false, null, true);
                                dbexpress.SetValue(column_value_key, true);
                                ref_dic = DB.Excute(up, dbexpress, true).QueryData<FrameDLRObject>()
                           .ToDictionary(k => k.GetValue(column_value_key), val => val.GetValue(column_text_key));
                            }

                            item.SetValue($"{c.MetaColumnName}__text", ref_dic.ContainsKey(v) ? ref_dic[v] : null);
                        }
                        else
                        {
                            item.SetValue($"{c.MetaColumnName}__text", null);
                        }
                    }
                }
                if (new string[] { "multi-select", "multi-pop", "checkbox" }.Contains((string)c.MetaDataType))
                {
                    List<FrameDLRObject> ref_list = new List<FrameDLRObject>();
                    if (refResult.Filter.Count <= 0)
                    {
                        var dbexpress = refResult.ToDBExpress(null, is_filter_deleted, null, false, null, true);
                        dbexpress.SetValue(column_value_key, true);
                        ref_list = DB.Excute(up, dbexpress, true).QueryData<FrameDLRObject>();
                    }


                    foreach (var item in data)
                    {
                        var v = item.GetValue(c.MetaColumnName);
                        if (v != null)
                        {
                            if (refResult.Filter.Count >= 0)
                            {
                                var ref_pk = ComFunc.nvl(item.GetValue("_default_ref"));
                                var main_ref_data = main_dic.ContainsKey(ref_pk) ? main_dic[ref_pk] : null;

                                var dbexpress = refResult.ToDBExpress(item, is_filter_deleted, main_ref_data, false, null, true);
                                dbexpress.SetValue(column_value_key, true);
                                ref_list = DB.Excute(up, dbexpress, true).QueryData<FrameDLRObject>();
                            }

                            var temp_array = (IEnumerable<object>)v;
                            var text = string.Join(",", ref_list.Where(w => temp_array.Contains(((FrameDLRObject)w).GetValue(column_value_key)))
                                .Select(d => ComFunc.nvl(d.GetValue(column_text_key))).OrderBy(o => o).ToArray());
                            item.SetValue($"{c.MetaColumnName}__text", text);
                        }
                        else
                        {
                            item.SetValue($"{c.MetaColumnName}__text", null);
                        }
                    }
                }
                #region 树结构级联
                if (new string[] { "cadecase_tree" }.Contains((string)c.MetaDataType))
                {
                    var ref_dic = new Dictionary<dynamic, dynamic>();
                    var dbexpress = refResult.ToDBExpress(null, is_filter_deleted, null, false, null, true);
                    dbexpress.SetValue(column_p_pk_key, true);
                    dbexpress.SetValue(column_pk_key, true);
                    var ref_list = DB.Excute(up, dbexpress, true).QueryData<FrameDLRObject>().Select(d =>
                    {
                        d.next_ref_pk = ((FrameDLRObject)d).GetValue(column_p_pk_key);
                        d.text = ((FrameDLRObject)d).GetValue(column_text_key);
                        return d;
                    }).ToList();



                    var is_continue = true;
                    do
                    {
                        is_continue = false;
                        var tpks = ref_list.Select(d => ComFunc.nvl(d.GetValue("next_ref_pk"))).ToArray();
                        var t_dic = (from t in DB.LamdaTable(up, refResult.TableName, "a")
                                     where t.column(column_pk_key).within(string.Join(",", tpks))
                                     select new
                                     {
                                         v = t.column(column_value_key),
                                         pk = t.column(column_pk_key),
                                         text = t.column(column_text_key),
                                         p_pk = t.column(column_p_pk_key)
                                     }).GetQueryList(up).ToDictionary(k => k.GetValue("pk"), v => v);
                        foreach (dynamic item in ref_list)
                        {
                            var p_pk = ComFunc.nvl(item.next_ref_pk);
                            if (p_pk != "")
                            {
                                is_continue = is_continue || true;
                            }
                            else
                            {
                                is_continue = is_continue || false;
                                continue;
                            }
                            var tpretext = t_dic.ContainsKey(p_pk) ? ComFunc.nvl(t_dic[p_pk].GetValue("text")) : "";
                            var tnext_ref_pk = t_dic.ContainsKey(p_pk) ? ComFunc.nvl(t_dic[p_pk].GetValue("p_pk")) : "";
                            if (tpretext == "") tpretext = "--";
                            if (t_dic.ContainsKey(p_pk))
                            {
                                item.text = $"{tpretext}/{item.text}";
                            }
                            item.next_ref_pk = tnext_ref_pk;
                        }
                    } while (is_continue);

                    ref_dic = ref_list.ToDictionary(k => k.GetValue(column_value_key), val => val.GetValue("text"));

                    foreach (var item in data)
                    {
                        var v = item.GetValue(c.MetaColumnName);
                        if (v != null)
                        {
                            item.SetValue($"{c.MetaColumnName}__text", ref_dic.ContainsKey(v) ? ref_dic[v] : null);
                        }
                        else
                        {
                            item.SetValue($"{c.MetaColumnName}__text", null);
                        }
                    }
                }
                if (new string[] { "multi_cadecase_tree" }.Contains((string)c.MetaDataType))
                {
                    var dbexpress = refResult.ToDBExpress(null, is_filter_deleted, null, false, null, true);
                    dbexpress.SetValue(column_p_pk_key, true);
                    dbexpress.SetValue(column_pk_key, true);
                    var ref_list = DB.Excute(up, dbexpress, true).QueryData<FrameDLRObject>().Select(d =>
                    {
                        d.next_ref_pk = ((FrameDLRObject)d).GetValue(column_p_pk_key);
                        d.text = ((FrameDLRObject)d).GetValue(column_text_key);
                        return d;
                    }).ToList();


                    var is_continue = true;
                    do
                    {
                        is_continue = false;
                        var tpks = ref_list.Select(d => ComFunc.nvl(d.GetValue("next_ref_pk")));
                        var t_dic = (from t in DB.LamdaTable(up, refResult.TableName, "a")
                                     where t.column(column_pk_key).within(string.Join(",", tpks))
                                     select new
                                     {
                                         v = t.column(column_value_key),
                                         pk = t.column(column_pk_key),
                                         text = t.column(column_text_key),
                                         p_pk = t.column(column_p_pk_key)
                                     }).GetQueryList(up).ToDictionary(k => k.GetValue("pk"), v => v);
                        foreach (dynamic item in ref_list)
                        {
                            var p_pk = ComFunc.nvl(item.next_ref_pk);
                            if (p_pk != "")
                            {
                                is_continue = is_continue || true;
                            }
                            else
                            {
                                is_continue = is_continue || false;
                                continue;
                            }
                            var tpretext = t_dic.ContainsKey(p_pk) ? ComFunc.nvl(t_dic[p_pk].GetValue("text")) : "";
                            var tnext_ref_pk = t_dic.ContainsKey(p_pk) ? ComFunc.nvl(t_dic[p_pk].GetValue("p_pk")) : "";
                            if (tpretext == "") tpretext = "--";
                            if (t_dic.ContainsKey(p_pk))
                            {
                                item.text = $"{tpretext}/{item.text}";
                            }
                            item.next_ref_pk = tnext_ref_pk;
                        }
                    } while (is_continue);

                    foreach (var item in data)
                    {
                        var v = item.GetValue(c.MetaColumnName);
                        if (v != null)
                        {
                            var temp_array = (IEnumerable<object>)v;
                            var text = string.Join(",", ref_list.Where(w => temp_array.Contains(((FrameDLRObject)w).GetValue(column_value_key)))
                                .Select(d => ComFunc.nvl(d.GetValue("text"))).OrderBy(o => o).ToArray());
                            item.SetValue($"{c.MetaColumnName}__text", text);
                        }
                        else
                        {
                            item.SetValue($"{c.MetaColumnName}__text", null);
                        }
                    }
                }
                #endregion
                #region 主从表级联控件
                if (new string[] { "cadecase_main", "multi_cadecase_main" }.Contains((string)c.MetaDataType))
                {
                    //搜索元数据表级联结构
                    var needed_table_list = BuildCadecaseMS_MetaTreeInfo(metaup, refResult.TableName);
                    if (needed_table_list.Count <= 0) continue;

                    if (column_text_key == "") column_text_key = "_default_pk";
                    var pks = new List<string>();
                    if (c.MetaDataType == "cadecase_main")
                        pks = data.Select(d => (string)ComFunc.nvl(d.GetValue((string)c.MetaColumnName))).Where(w => !string.IsNullOrEmpty(w)).ToList();
                    else
                    {
                        foreach (var item in data)
                        {
                            var v = (IEnumerable<object>)item.GetValue((string)c.MetaColumnName);
                            if (v != null && v.Count() > 0)
                                pks.AddRange(v.Select(d => ComFunc.nvl(d)).Where(w => !string.IsNullOrEmpty(w)));
                        }
                    }


                    var ref_list = (from t in DB.LamdaTable(up, refResult.TableName, "a")
                                    where t.iftrue(is_filter_deleted, t._is_deleted == 0) && t.column(refResult.KeyColumn).within(string.Join(",", pks))
                                    select new
                                    {
                                        code = t.column(refResult.KeyColumn),
                                        text = t.column(column_text_key),
                                        t._default_pk,
                                        ref_pk = t._default_ref,
                                        next_ref_pk = t._default_ref
                                    }).GetQueryList(up);//.ToDictionary(k => k.GetValue("code"), val => val.GetValue("text"));
                                                        //逆向递归，找出级联层级，使text显示层级
                    var curtableinfo = needed_table_list.Where(w => w.MetaName == refResult.TableName).FirstOrDefault();
                    if (curtableinfo == null) continue;
                    var level = IntStd.IsNotIntThen(curtableinfo.TreeLevel);
                    var meta_show_column = ComFunc.nvl(curtableinfo.MetaMainShowColumn);
                    for (var i = level - 1; i > 0; i--)
                    {
                        var ti = needed_table_list.Where(w => w.TreeLevel == i).FirstOrDefault();
                        if (ti == null) continue;
                        var tn = ComFunc.nvl(ti.MetaName);
                        var tpks = ref_list.Select(d => ComFunc.nvl(d.GetValue("next_ref_pk")));
                        var tdic = (from t in DB.LamdaTable(up, tn, "a")
                                    where t._default_pk.within(string.Join(",", tpks))
                                    select new
                                    {
                                        code = t._default_pk,
                                        text = t.column(meta_show_column),
                                        ref_pk = t._default_ref,
                                        next_ref_pk = t._default_ref
                                    }).GetQueryList(up).ToDictionary(k => ComFunc.nvl(k.GetValue("code")), v => v);
                        foreach (dynamic item in ref_list)
                        {
                            var tkey = ComFunc.nvl(item.next_ref_pk);
                            if (tkey == "") continue;
                            var tpretext = tdic.ContainsKey(tkey) ? ComFunc.nvl(tdic[tkey].GetValue("text")) : "";
                            var tnext_ref_pk = tdic.ContainsKey(tkey) ? ComFunc.nvl(tdic[tkey].GetValue("next_ref_pk")) : "";
                            if (tpretext == "") tpretext = "--";
                            if (tdic.ContainsKey(tkey))
                            {
                                item.text = $"{tpretext}/{item.text}";
                            }
                            item.next_ref_pk = tnext_ref_pk;
                        }
                        meta_show_column = ComFunc.nvl(ti.MetaMainShowColumn);
                    }

                    var ref_dic = ref_list.ToDictionary(k => k.GetValue("code"), val => val.GetValue("text"));



                    foreach (var item in data)
                    {
                        var v = item.GetValue(c.MetaColumnName);
                        if (v != null)
                        {
                            var text = "";
                            if (c.MetaDataType == "cadecase_main")
                            {
                                text = ref_dic.ContainsKey(v) ? ref_dic[v] : null;
                            }
                            else
                            {
                                var temp_array = ((IEnumerable<object>)v).Select(d => ComFunc.nvl(d)).ToArray();
                                text = string.Join(",", ref_dic.Where(w => temp_array.Contains((string)ComFunc.nvl(w.Key)))
                                .Select(d => d.Value).OrderBy(o => o).ToArray());
                            }

                            item.SetValue($"{c.MetaColumnName}__text", text);
                        }
                        else
                        {
                            item.SetValue($"{c.MetaColumnName}__text", null);
                        }
                    }
                }
                #endregion
            }
        }
    }
    #endregion
}
}
